home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
archiver
/
unix
/
zip19p1.zoo
/
match.s
< prev
next >
Wrap
Text File
|
1992-08-13
|
5KB
|
147 lines
/
/ Copyright (C) 1990-1992 Mark Adler, Richard B. Wales, Jean-loup Gailly,
/ Kai Uwe Rommel and Igor Mandrichenko.
/ Permission is granted to any individual or institution to use, copy, or
/ redistribute this software so long as all of the original files are included
/ unmodified, that it is not sold for profit, and that this copyright notice
/ is retained.
/
/ match.s by Jean-loup Gailly. Translated to 32 bit code by Kai Uwe Rommel.
/ match.s, optimized version of longest_match() in deflate.c
/ This version is for 386 Unix or OS/2 in 32 bit mode.
/ Warning: it uses the AT&T syntax: mov source,dest
/ This file is only optional. If you want to force the C version,
/ add -DNO_ASM to CFLAGS in makefile and remove match.o from OBJI).
/ If you have reduced WSIZE in zip.h, then change its value below.
/ This version assumes static allocation of the arrays (-DDYN_ALLOC not used).
.file "match.s"
#if defined(__GO32__) && defined(unix)
# undef unix
#endif
#ifdef unix
# define _prev prev
# define _window window
# define _match_start match_start
# define _prev_length prev_length
# define _good_match good_match
# define _strstart strstart
# define _max_chain_length max_chain_length
# define _match_init match_init
# define _longest_match longest_match
#endif
#define MAX_MATCH 258
#define MAX_MATCH2 128 /* MAX_MATCH/2-1 */
#define MIN_MATCH 3
#define WSIZE 32768
#define MAX_DIST WSIZE - MAX_MATCH - MIN_MATCH - 1
.globl _match_init
.globl _longest_match
.text
_match_init:
ret
/ -----------------------------------------------------------------------
/ Set match_start to the longest match starting at the given string and
/ return its length. Matches shorter or equal to prev_length are discarded,
/ in which case the result is equal to prev_length and match_start is
/ garbage.
/ IN assertions: cur_match is the head of the hash chain for the current
/ string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
_longest_match: /* int longest_match(cur_match) */
#define cur_match 20(%esp)
/ return address / esp+16
push %ebp / esp+12
push %edi / esp+8
push %esi / esp+4
push %ebx / esp
/ match equ esi
/ scan equ edi
/ chain_length equ ebp
/ best_len equ ebx
/ limit equ edx
mov cur_match,%esi
mov _max_chain_length,%ebp / chain_length = max_chain_length
mov _strstart,%edi
mov %edi,%edx
sub $ MAX_DIST,%edx / limit = strstart-MAX_DIST
jae limit_ok
sub %edx,%edx / limit = NIL
limit_ok:
add $_window+2,%edi / edi = offset(window + strstart + 2)
mov _prev_length,%ebx / best_len = prev_length
movw -3(%ebx,%edi),%ax / ax = scan[best_len-1..best_len]
movw -2(%edi),%cx / cx = scan[0..1]
cmp _good_match,%ebx / do we have a good match already?
jb do_scan
shr $2,%ebp / chain_length >>= 2
jmp do_scan
.align 4
long_loop:
/ at this point, edi == scan+2, esi == cur_match
movw -3(%ebx,%edi),%ax / ax = scan[best_len-1..best_len]
movw -2(%edi),%cx / cx = scan[0..1]
short_loop:
dec %ebp / --chain_length
jz the_end
/ at this point, di == scan+2, si == cur_match,
/ ax = scan[best_len-1..best_len] and cx = scan[0..1]
and $ WSIZE-1, %esi
movw _prev(%esi,%esi),%si / cur_match = prev[cur_match]
/ top word of esi is still 0
cmp %edx,%esi / cur_match <= limit ?
jbe the_end
do_scan:
cmpw _window-1(%ebx,%esi),%ax /check match at best_len-1
jne short_loop
cmpw _window(%esi),%cx / check min_match_length match
jne short_loop
lea _window+2(%esi),%esi / si = match
mov %edi,%eax / ax = scan+2
mov $ MAX_MATCH2,%ecx / scan for at most MAX_MATCH bytes
#ifdef unix
repz; cmpsw / loop until mismatch
#else
repe; cmpsw
#endif
je maxmatch / match of length MAX_MATCH?
mismatch:
movb -2(%edi),%cl / mismatch on first or second byte?
subb -2(%esi),%cl / cl = 0 if first bytes equal
xchg %edi,%eax / edi = scan+2, eax = end of scan
sub %edi,%eax / eax = len
sub %eax,%esi / esi = cur_match + 2 + offset(window)
sub $_window+2,%esi / esi = cur_match
subb $1,%cl / set carry if cl == 0 (cannot use DEC)
adc $0,%eax / eax = carry ? len+1 : len
cmp %ebx,%eax / len > best_len ?
jle long_loop
mov %esi,_match_start / match_start = cur_match
mov %eax,%ebx / ebx = best_len = len
cmp $ MAX_MATCH,%eax / len >= MAX_MATCH ?
jl long_loop
the_end:
mov %ebx,%eax / result = eax = best_len
pop %ebx
pop %esi
pop %edi
pop %ebp
ret
maxmatch:
cmpsb
jmp mismatch